package com.bc.commoncore.util;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.net.ssl.*;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class PostAndGetImpl {
    private static final String SERVLET_POST = "POST";
    private static final String SERVLET_GET = "GET";
    private static final String SERVLET_DELETE = "DELETE";
    private static final String SERVLET_PUT = "PUT";
    private static final int ConnectTimeout = 30000;
    private static final int ReadTimeout = 30000;
    private static ThreadLocal<Map<String, String>> catMessageIdsMapHolder = new ThreadLocal<>();
    private static final Logger logger = LoggerFactory.getLogger(PostAndGetImpl.class);

    private static Map<String, String> getCatMessageIdsMap() {
        return catMessageIdsMapHolder.get();
    }

    public static void setCatMessageIdsMap(Map<String, String> catMessageIdsMap) {
        catMessageIdsMapHolder.set(catMessageIdsMap);
    }

    /**
     * 通过post调用外部接口时添加附件
     *
     * @param url
     * @param conn
     */
    private static void setHttpPostAttachment(String url, URLConnection conn) {
        if (StringUtils.isEmpty(url) || !url.contains("/services/") || conn == null) {
            return;
        }
        Map<String, String> catMessageIdsMap = getCatMessageIdsMap();
        if (catMessageIdsMap == null || catMessageIdsMap.isEmpty()) {
            return;
        }
        //由于nginx默认配置下,不允许header中的keyname中包含_,
        //因此调用外部接口给header赋值时,这里的keyname都去掉了_
        String rootId = "catRootMessageId";
        String parentId = "catParentMessageId";
        String childID = "catChildMessageId";
        if (catMessageIdsMap.containsKey("_" + rootId)) {
            conn.setRequestProperty(rootId, catMessageIdsMap.get("_" + rootId));
        }
        if (catMessageIdsMap.containsKey("_" + parentId)) {
            conn.setRequestProperty(parentId, catMessageIdsMap.get("_" + parentId));
        }
        if (catMessageIdsMap.containsKey("_" + childID)) {
            conn.setRequestProperty(childID, catMessageIdsMap.get("_" + childID));
        }
    }

    private String getCauseBy(String url, Exception e, String param) {
        String causeBy = ParseHelper.filterCauseBy(e);
        String result = "发送 PostGet请求出现异常:" + causeBy + ";param:" + param;
        ;
        if (causeBy.indexOf(url) < 0) {
            result = url + result;
        }
        return result;
    }
//	public static void main(String[] args) {
//		String url="http://acsnetapi.zhanghetianxia.com/as/sync/register?a=";
//		String s=urlEncode(url);
//		System.out.println(s);
//	}

    /**
     * 对get请求的url进行encode
     * 例如：
     *
     * @param url
     * @return
     */
    public static String urlEncode(String url) {
        if (StringUtils.isEmpty(url)) {
            return url;
        }
        if (url.indexOf("http://") < 0 && url.indexOf("https://") < 0) {
            return url;
        }
        int index = url.indexOf("?");
        if (index < 0) {
            return url;
        }
        if (url.length() <= index + 1) {
            return url;
        }
        String domain = url.substring(0, index);
        String param = url.substring(index + 1);
        if (StringUtils.isEmpty(param)) {
            return url;
        }
        if (param.indexOf("=") <= 0) {
            return url;
        }
        Map<String, String> paramMap = new HashMap<String, String>();
        String[] keyvalue = param.split("&");
        for (String string : keyvalue) {
            if (!StringUtils.isEmpty(string)) {
                if (string.indexOf("=") > 0) {
                    String[] pair = string.split("=");
                    if (pair.length > 0) {
                        if (pair.length > 1) {
                            paramMap.put(pair[0].trim(), pair[1].trim());
                        } else {
                            paramMap.put(pair[0].trim(), "");
                        }
                    }
                }
            }
        }
        if (!paramMap.isEmpty()) {
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                sb.append("&");
                sb.append(entry.getKey());
                sb.append("=");
                if (!StringUtils.isEmpty(entry.getValue())) {
                    String value = entry.getValue();
                    try {
                        //没有进行过url编码时，才需要进行url编码
                        if (!isHasEncode(entry.getValue())) {
                            value = URLEncoder.encode(entry.getValue(), "utf-8");
                        }
                    } catch (Exception e) {
                        logger.error("get请求参数进行url编码时异常:" + e.getMessage());
                    }
                    sb.append(value);
                }
            }
            return domain + "?" + sb.toString().substring(1);
        }

        return url;
    }

    /**
     * 判断字符串是否进行过url编码
     * 多次url编码会导致解码错误
     * 因此需要先判断是否需要进行url编码，
     * 判断方法：先解码，如果解码后的值和原值相等，则说明原值没有进行过url编码
     *
     * @param str
     * @return
     */
    private static boolean isHasEncode(String str) {
        if (StringUtils.isEmpty(str)) {
            return true;
        }
        try {
            String decodeValue = URLDecoder.decode(str, "utf-8");
            if (!decodeValue.equals(str)) {
                return true;
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    public String sendMapGet(String url, Map<String, Object> params) {

        return sendGet(url, prepareParam(params), null);
    }

    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url   发送请求的URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public String sendGet(String url, String param, String cookies) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url;
            param = (param == null ? "" : param);
            if (url.indexOf("?") > 0) {
                urlNameString = url + param;
            } else if (!param.isEmpty()) {
                urlNameString = url + "?" + param;
            }
            //get请求时对键值对里面的值进行url编码，防止报错
            //2017-12-27，zhaohl
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            if (connection instanceof HttpsURLConnection) {
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null,
                        new TrustManager[]{new TrustAnyTrustManager()},
                        new java.security.SecureRandom());
                ((HttpsURLConnection) connection).setSSLSocketFactory(sc
                        .getSocketFactory());
                ((HttpsURLConnection) connection)
                        .setHostnameVerifier(new TrustAnyHostnameVerifier());
            }
            // 设置通用的请求属性
//            connection.setRequestProperty("content-type","text/html; charset=utf-8");
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("TE", "Trailers");

            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:66.0) Gecko/20100101 Firefox/66.0");
            if (cookies != null && !cookies.isEmpty()) {
                connection.setRequestProperty("Cookie", cookies);
            }
            connection.setConnectTimeout(ConnectTimeout);
            connection.setReadTimeout(ReadTimeout);

            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            // Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            // for (String key : map.keySet()) {
            // System.out.println(key + "--->" + map.get(key));
            // }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            result = new String(result.getBytes(), "utf-8");
        } catch (Exception e) {
            throw new RuntimeException(getCauseBy(url, e, param));
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {

            }
        }
        return result;
    }


    private static class TrustAnyTrustManager implements X509TrustManager {

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }
    }

    private static class TrustAnyHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public String sendPost(String url, String param, String contentType,
                           String cookies) {
        PrintWriter out = null;
        InputStream in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            if (contentType != null && !contentType.isEmpty()) {
                conn.setRequestProperty("Content-Type", contentType); // 设置发
            }
            if (cookies != null && !cookies.isEmpty()) {
                conn.setRequestProperty("Cookie", cookies);
            }
            //把当前项目的消息id传递出去，构建分布式消息树
            setHttpPostAttachment(url, conn);
            conn.setConnectTimeout(ConnectTimeout);
            conn.setReadTimeout(ReadTimeout);

            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            // in = new BufferedReader(
            // new InputStreamReader(conn.getInputStream(),"UTF-8"));
            // String line;
            // while ((line = in.readLine()) != null) {
            // result += line;
            // }
            in = conn.getInputStream();
            result = StreamUtils.copyToString(in, Charset.forName("utf-8"));
        } catch (Exception e) {
            // System.out.println("发送 POST 请求出现异常！"+e);
            // e.printStackTrace();
            throw new RuntimeException(getCauseBy(url, e, param));
        }
        // 使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {

            }
        }
        return result;
    }

    /**
     * 上传文件
     *
     * @param urlStr
     * @param urlStr
     * @param fileName
     * @return
     */
    public String sendPostAndUpload(String urlStr, String fileName,
                                    InputStream input) {
        return sendPostAndUpload(urlStr, null, fileName, input);
    }

    /**
     * 上传文件附加参数
     *
     * @param urlStr
     * @param param
     * @param fileName
     * @param input
     * @return
     */
    public String sendPostAndUpload(String urlStr, Map<String, String> param, String fileName, InputStream input) {
        InputStream in = null;
        String BOUNDARY = java.util.UUID.randomUUID().toString();
        String PREFFIX = "--", LINEND = "\r\n";
        String MULTIPART_FROM_DATA = "multipart/form-data";
        String CHARSET = "UTF-8";
        URL uri;
        String result = "";
        try {
            uri = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) uri.openConnection();// 设置从主机读取数据超时
            conn.setConnectTimeout(ConnectTimeout);
            conn.setReadTimeout(ReadTimeout);
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("connection", "keep-alive");
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);
            DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
            // 首先组拼文本类型的参数
            if (param != null && param.size() > 0) {
                StringBuilder paramStr = new StringBuilder();
                for (Map.Entry<String, String> entry : param.entrySet()) {
                    paramStr.append(PREFFIX);
                    paramStr.append(BOUNDARY);
                    paramStr.append(LINEND);
                    paramStr.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND);
                    paramStr.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
                    paramStr.append("Content-Transfer-Encoding: 8bit" + LINEND);
                    paramStr.append(LINEND);
                    paramStr.append(entry.getValue());
                    paramStr.append(LINEND);

                }
                outStream.write(paramStr.toString().getBytes(CHARSET));
            }

            // 构建发送字符串数据
            StringBuilder paramStr1 = new StringBuilder();
            paramStr1.append(PREFFIX);
            paramStr1.append(BOUNDARY);
            paramStr1.append(LINEND);
            paramStr1.append("Content-Disposition: form-data; name=\"Filedata\"; filename=\"" + fileName + "\"" + LINEND);
            paramStr1.append("Content-Type: application/octet-stream;chartset=" + CHARSET + LINEND);
            paramStr1.append(LINEND);
            // 写入到输出流中
            outStream.write(paramStr1.toString().getBytes());

            // 将文件读入输入流中
            byte[] buffer = new byte[1024];
            int len = 0;
            // 写入输出流
            while ((len = input.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
            input.close(); // 添加换行标志
            outStream.write(LINEND.getBytes());
            // 请求结束标志
            byte[] end_data = (PREFFIX + BOUNDARY + PREFFIX + LINEND).getBytes();
            outStream.write(end_data); // 刷新发送数据
            outStream.flush(); // 得到响应码
            int res = conn.getResponseCode();

            // 上传成功返回200
            if (res == 200) {
                in = conn.getInputStream();
                result = StreamUtils.copyToString(in, Charset.forName(CHARSET));
                in.close();
            }
            conn.disconnect();
        } catch (Exception e) {
            throw new RuntimeException(getCauseBy(urlStr, e, ""));
        }
        return result;
    }

    private static String prepareParam(Map<String, Object> paramMap) {
        StringBuffer sb = new StringBuffer();
        if (paramMap.isEmpty()) {
            return "";
        } else {
            for (String key : paramMap.keySet()) {
                String value = (String) paramMap.get(key);
                if (sb.length() < 1) {
                    sb.append(key).append("=").append(value);
                } else {
                    sb.append("&").append(key).append("=").append(value);
                }
            }
            return sb.toString();
        }
    }

    public void doPut(String urlStr, Object obj) {
        doPut(urlStr, JsonUtil.obj2string(obj));
    }

    public void doPut(String urlStr, Map<String, Object> paramMap) {
        doPut(urlStr, prepareParam(paramMap));
    }

    private void doPut(String urlStr, String paramStr) {
        BufferedReader br = null;
        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod(SERVLET_PUT);
            // String paramStr = parm;
            conn.setConnectTimeout(ConnectTimeout);
            conn.setReadTimeout(ReadTimeout);
            conn.setDoInput(true);
            conn.setDoOutput(true);
            OutputStream os = conn.getOutputStream();
            os.write(paramStr.toString().getBytes("utf-8"));
            os.close();

            br = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            String result = "";
            while ((line = br.readLine()) != null) {
                result += "/n" + line;
            }
        } catch (Exception e) {
            throw new RuntimeException(getCauseBy(urlStr, e, paramStr));
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (Exception e2) {

            }
        }

    }

    public String HttpPut(String postUrl, Map<String, String> postHeaders,
                          String postEntity) {
        BufferedReader in = null;
        try {
            URL postURL = new URL(postUrl);
            HttpURLConnection httpURLConnection = (HttpURLConnection) postURL
                    .openConnection();
            httpURLConnection.setConnectTimeout(ConnectTimeout);
            httpURLConnection.setReadTimeout(ReadTimeout);
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            httpURLConnection.setRequestMethod("PUT");
            httpURLConnection.setUseCaches(false);
            httpURLConnection.setInstanceFollowRedirects(true);
            httpURLConnection.setRequestProperty("Content-Type",
                    "application/json;charset=utf-8");// json格式上传的模式
            StringBuilder sbStr = new StringBuilder();
            if (postHeaders != null) {
                for (String pKey : postHeaders.keySet()) {
                    httpURLConnection.setRequestProperty(pKey,
                            postHeaders.get(pKey));
                }
            }
            if (postEntity != null) {

                PrintWriter out = new PrintWriter(new OutputStreamWriter(
                        httpURLConnection.getOutputStream(), "utf-8"));
                out.println(postEntity);
                out.close();
                in = new BufferedReader(new InputStreamReader(
                        httpURLConnection.getInputStream()));

                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    sbStr.append(inputLine);
                }
                in.close();
            }
            httpURLConnection.disconnect();
            return new String(sbStr.toString().getBytes(), "utf-8");
        } catch (Exception e) {
            throw new RuntimeException(getCauseBy(postUrl, e, ""));
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {

            }
        }
    }

    public int doDelete(String urlStr, Map<String, Object> paramMap) {
        try {
            String paramStr = prepareParam(paramMap);
            if (paramStr == null || paramStr.trim().length() < 1) {

            } else {
                urlStr += "?" + paramStr;
            }

            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(ConnectTimeout);
            conn.setReadTimeout(ReadTimeout);
            conn.setDoOutput(true);
            conn.setRequestMethod(SERVLET_DELETE);
            return conn.getResponseCode();
        } catch (Exception e) {
            throw new RuntimeException(getCauseBy(urlStr, e, ""));
        }
    }

    /**
     * 封装HTTP POST方法
     *
     * @param
     * @param
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String sendMapPost(String url, Map<String, String> paramMap) {

        String httpEntityContent = null;
        CloseableHttpClient httpClient = null;
        try {
            //HttpClient httpClient = new DefaultHttpClient();
            httpClient = HttpClientBuilder.create().build();
            HttpPost httpPost = new HttpPost(url);
            // 设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(ReadTimeout).setConnectTimeout(ConnectTimeout).build();
            httpPost.setConfig(requestConfig);
            List<NameValuePair> formparams = HttpClientUtil
                    .setHttpParams(paramMap);
            UrlEncodedFormEntity param = new UrlEncodedFormEntity(formparams,
                    "UTF-8");
            httpPost.setEntity(param);
            HttpResponse response = httpClient.execute(httpPost);
            httpEntityContent = HttpClientUtil.getHttpEntityContent(response);
            httpPost.abort();
            return httpEntityContent;
        } catch (Exception ex) {
            throw new RuntimeException(getCauseBy(url, ex, ""));
        } finally {
            if (httpClient != null) {
                try {
                    //释放资源
                    httpClient.close();
                } catch (IOException e) {
                }
            }
        }
    }


    //region 营业执照方法

    /**
     * Post String
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public HttpResponse doPostBusinessLicense(String host, String path, String method,
                                              Map<String, String> headers,
                                              Map<String, String> querys,
                                              String body) {
        CloseableHttpClient httpClient = null;
        try {
            httpClient = wrapClient(host);
            HttpPost request = new HttpPost(buildUrl(host, path, querys));
            for (Map.Entry<String, String> e : headers.entrySet()) {
                request.addHeader(e.getKey(), e.getValue());
            }
            if (org.apache.commons.lang.StringUtils.isNotBlank(body)) {
                request.setEntity(new StringEntity(body, "utf-8"));
            }

            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(ReadTimeout).setConnectTimeout(ConnectTimeout).build();
            request.setConfig(requestConfig);

            return httpClient.execute(request);
        } catch (Exception ex) {
            throw new RuntimeException(getCauseBy(host + path, ex, body));
        } finally {
            /*if (httpClient != null) {
                try {
                    //释放资源
                    httpClient.close();
                } catch (IOException e) {
                }
            }*/
        }


    }

    private static CloseableHttpClient wrapClient(String host) {
        CloseableHttpClient httpClient = new DefaultHttpClient();
        if (host.startsWith("https://")) {
            sslClient(httpClient);
        }

        return httpClient;
    }


    private static void sslClient(HttpClient httpClient) {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] xcs, String str) {

                }

                public void checkServerTrusted(X509Certificate[] xcs, String str) {

                }
            };
            ctx.init(null, new TrustManager[]{tm}, null);
            org.apache.http.conn.ssl.SSLSocketFactory ssf = new org.apache.http.conn.ssl.SSLSocketFactory(ctx);
            ssf.setHostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = httpClient.getConnectionManager();
            SchemeRegistry registry = ccm.getSchemeRegistry();
            registry.register(new Scheme("https", 443, ssf));
        } catch (KeyManagementException ex) {
            throw new RuntimeException(ex);
        } catch (NoSuchAlgorithmException ex) {
            throw new RuntimeException(ex);
        }
    }

    private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
        StringBuilder sbUrl = new StringBuilder();
        sbUrl.append(host);
        if (!org.apache.commons.lang.StringUtils.isBlank(path)) {
            sbUrl.append(path);
        }
        if (null != querys) {
            StringBuilder sbQuery = new StringBuilder();
            for (Map.Entry<String, String> query : querys.entrySet()) {
                if (0 < sbQuery.length()) {
                    sbQuery.append("&");
                }
                if (org.apache.commons.lang.StringUtils.isBlank(query.getKey()) && !org.apache.commons.lang.StringUtils.isBlank(query.getValue())) {
                    sbQuery.append(query.getValue());
                }
                if (!org.apache.commons.lang.StringUtils.isBlank(query.getKey())) {
                    sbQuery.append(query.getKey());
                    if (!org.apache.commons.lang.StringUtils.isBlank(query.getValue())) {
                        sbQuery.append("=");
                        sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
                    }
                }
            }
            if (0 < sbQuery.length()) {
                sbUrl.append("?").append(sbQuery);
            }
        }

        return sbUrl.toString();
    }

    //endregion

}
